package com.vc.utils;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.*;

// 生成jwt
public class JwtUtils {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
    public static final long EXPIRATION_TIME = 3600_000_000L; // 1000 hour
    public static final String SECRET = "ThisIsASecret";// 密钥
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String HEADER_STRING = "Authorization";
    public static final String USER_NAME = "userName";

    // 生成token
    public static String generateToken(String username) {
        HashMap<String, Object> map = new HashMap<>();
        //you can put any data in the map
        map.put(USER_NAME, username);

        // 使用Jwts包生成jwt
        String jwt = Jwts.builder() // 创建一个对象
                .setClaims(map) // 要加密的数据
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 超期时间 超过该时间需要重新登录
                .signWith(SignatureAlgorithm.HS512, SECRET) // 使用签名算法进行加密，定义成字符串
                .compact(); // 压缩成乱码的字符串
        return jwt; // jwt前面一般都会加Bearer
    }

    // 校验token并添加到请求头
    public static HttpServletRequest validateTokenAndAddUserIdToHeader(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            try {
                Map<String, Object> body = Jwts.parser() // 解析
                        .setSigningKey(SECRET) // 使用这个密钥加密 也得使用这个密钥解密
                        .parseClaimsJws(token.replace(TOKEN_PREFIX, "")) // 将前端传来的前缀Bearer 替换成""
                        .getBody(); // 解析出来的token

                // 将解析出来的用户名添加到请求头中 生成新的http请求对象
                return new CustomHttpServletRequest(request, body);
            } catch (Exception e) {
                logger.info(e.getMessage());
                throw new TokenValidationException(e.getMessage());
            }
        } else {
            throw new TokenValidationException("Missing token");
        }
    }

    // 定义一个HTTP请求类的子类
    public static class CustomHttpServletRequest extends HttpServletRequestWrapper {
        private Map<String, String> claims;

        // 将token解析出来的map 传过来
        public CustomHttpServletRequest(HttpServletRequest request, Map<String, ?> claims) {
            super(request);
            this.claims = new HashMap<>();

            // 对传进来的map进行循环 将每个键值对传到私有的map中
            claims.forEach((k, v) -> this.claims.put(k, String.valueOf(v)));
        }

        // 重写父类方法
        @Override
        public Enumeration<String> getHeaders(String name) {
            // 先查看传过来的map中是否包含传进来的key
            if (claims != null && claims.containsKey(name)) {
                // 将key对应到的值拿到返回回去
                return Collections.enumeration(Arrays.asList(claims.get(name)));
            }
            return super.getHeaders(name);
        }

    }

    //
    static class TokenValidationException extends RuntimeException {
        public TokenValidationException(String msg) {
            super(msg);
        }
    }
}
